home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Mud 4.0 / make_func.y < prev    next >
Encoding:
Lex Description  |  1992-12-01  |  10.3 KB  |  465 lines  |  [TEXT/MPS ]

  1. %{
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include "lint.h"
  7. #include "config.h"
  8.  
  9. #undef open
  10. #undef fopen
  11.  
  12. #ifndef mac
  13. #define FUNC_SPEC     "make list_funcs"
  14. #else
  15. #undef fopen
  16. #define FUNC_SPEC    "list_funcs"
  17. #endif
  18. #define FUNC_TOKENS     "efun_tokens.y"
  19. #define PRE_LANG        "prelang.y"
  20. #define POST_LANG       "postlang.y"
  21. #define THE_LANG        "lang.y"
  22. #define BUFSIZ         1024
  23. #define NELEMS(arr)     (sizeof arr / sizeof arr[0])
  24.  
  25. #define MAX_FUNC      2048  /* If we need more than this we're in trouble! */
  26. int num_buff;
  27. /* For quick sort purposes : */
  28. char *key[MAX_FUNC], *buf[MAX_FUNC], has_token[MAX_FUNC];
  29.  
  30. int min_arg = -1, limit_max = 0;
  31.  
  32. /*
  33.  * arg_types is the types of all arguments. A 0 is used as a delimiter,
  34.  * marking next argument. An argument can have several types.
  35.  */
  36. int arg_types[200], last_current_type;
  37. /*
  38.  * Store the types of the current efun. They will be copied into the
  39.  * arg_types list if they were not already there (to save memory).
  40.  */
  41. #undef MAX_LOCAL
  42. #define MAX_LOCAL 20
  43. int curr_arg_types[MAX_LOCAL], curr_arg_type_size;
  44.  
  45. void yyerror PROT((char *));
  46. int yylex();
  47. int yyparse();
  48. int ungetc PROT((int c, FILE *f));
  49. char *type_str PROT((int)), *etype PROT((int)), *etype1 PROT((int)),
  50.    *ctype PROT((int));
  51. #ifndef toupper
  52. int toupper PROT((int));
  53. #endif
  54.  
  55. void fatal(str)
  56.     char *str;
  57. {
  58.     fprintf(stderr, "%s", str);
  59.     exit(1);
  60. }
  61.  
  62. %}
  63. %union {
  64.     int number;
  65.     char *string;
  66. }
  67.  
  68. %token ID
  69.  
  70. %token VOID INT STRING OBJECT MIXED UNKNOWN MAPPING
  71.  
  72. %token DEFAULT
  73.  
  74. %type <number> type VOID INT STRING OBJECT MIXED UNKNOWN MAPPING arg_list basic typel
  75. %type <number> arg_type typel2
  76.  
  77. %type <string> ID optional_ID optional_default
  78.  
  79. %%
  80.  
  81. funcs: /* empty */ | funcs func ;
  82.  
  83. optional_ID: ID | /* empty */ { $$ = ""; } ;
  84.  
  85. optional_default: DEFAULT ':' ID { $$ = $3; } | /* empty */ { $$="0"; } ;
  86.  
  87. func: type ID optional_ID '(' arg_list optional_default ')' ';'
  88.     {
  89.     char buff[500];
  90.     char f_name[500];
  91.     int i;
  92.     if (min_arg == -1)
  93.         min_arg = $5;
  94.     if ($3[0] == '\0') {
  95.         int len;
  96.         if (strlen($2) + 1 + 2 > sizeof f_name)
  97.         fatal("A local buffer was too small!(1)\n");
  98.         sprintf(f_name, "F_%s", $2);
  99.         len = strlen(f_name);
  100.         for (i=0; i < len; i++) {
  101.         if (islower(f_name[i]))
  102.             f_name[i] = toupper(f_name[i]);
  103.         }
  104.         has_token[num_buff]=1;
  105.     } else {
  106.         if (strlen($3) + 1 > sizeof f_name)
  107.         fatal("A local buffer was too small(2)!\n");
  108.         strcpy(f_name, $3);
  109.         has_token[num_buff]=0;
  110.     }
  111.     for(i=0; i < last_current_type; i++) {
  112.         int j;
  113.         for (j = 0; j+i<last_current_type && j < curr_arg_type_size; j++)
  114.         {
  115.         if (curr_arg_types[j] != arg_types[i+j])
  116.             break;
  117.         }
  118.         if (j == curr_arg_type_size)
  119.         break;
  120.     }
  121.     if (i == last_current_type) {
  122.         int j;
  123.         for (j=0; j < curr_arg_type_size; j++) {
  124.         arg_types[last_current_type++] = curr_arg_types[j];
  125.         if (last_current_type == NELEMS(arg_types))
  126.             yyerror("Array 'arg_types' is too small");
  127.         }
  128.     }
  129.     sprintf(buff, "{\"%s\",%s,%d,%d,%s,%s,%s,%d,%s},\n",
  130.         $2, f_name, min_arg, limit_max ? -1 : $5, ctype($1),
  131.         etype(0), etype(1), i, $6);
  132.         if (strlen(buff) > sizeof buff)
  133.              fatal("Local buffer overwritten !\n");
  134.         key[num_buff] = (char *) malloc(strlen($2) + 1);
  135.     strcpy(key[num_buff], $2);
  136.     buf[num_buff] = (char *) malloc(strlen(buff) + 1);
  137.     strcpy(buf[num_buff], buff);
  138.         num_buff++;
  139.     min_arg = -1;
  140.     limit_max = 0;
  141.     curr_arg_type_size = 0;
  142.     } ;
  143.  
  144. type: basic | basic '*' { $$ = $1 | 0x10000; };
  145.  
  146. basic: VOID | INT | STRING | MIXED | UNKNOWN | OBJECT | MAPPING ;
  147.  
  148. arg_list: /* empty */        { $$ = 0; }
  149.     | typel2            { $$ = 1; if ($1) min_arg = 0; }
  150.     | arg_list ',' typel2     { $$ = $1 + 1; if ($3) min_arg = $$ - 1; } ;
  151.  
  152. typel2: typel
  153.     {
  154.     $$ = $1;
  155.     curr_arg_types[curr_arg_type_size++] = 0;
  156.     if (curr_arg_type_size == NELEMS(curr_arg_types))
  157.         yyerror("Too many arguments");
  158.     } ;
  159.  
  160. arg_type: type
  161.     {
  162.     if ($1 != VOID) {
  163.         curr_arg_types[curr_arg_type_size++] = $1;
  164.         if (curr_arg_type_size == NELEMS(curr_arg_types))
  165.         yyerror("Too many arguments");
  166.     }
  167.     $$ = $1;
  168.     } ;
  169.  
  170. typel: arg_type            { $$ = ($1 == VOID && min_arg == -1); }
  171.      | typel '|' arg_type     { $$ = (min_arg == -1 && ($1 || $3 == VOID));}
  172.      | '.' '.' '.'        { $$ = min_arg == -1 ; limit_max = 1; } ;
  173.  
  174. %%
  175.  
  176. struct type {
  177.     char *name;
  178.     int num;
  179. } types[] = {
  180. { "void", VOID },
  181. { "int", INT },
  182. { "string", STRING },
  183. { "object", OBJECT },
  184. { "mixed", MIXED },
  185. { "unknown", UNKNOWN },
  186. { "mapping", MAPPING }
  187. };
  188.  
  189. FILE *f;
  190. int current_line = 1;
  191.  
  192. int main(argc, argv)
  193.     int argc;
  194.     char **argv;
  195. {
  196.     int i, fdr, fdw;
  197.     char buffer[BUFSIZ + 1];
  198.  
  199. #ifdef mac
  200.     #pragma unused(argc,argv)
  201. #endif
  202.  
  203. #ifndef mac
  204.     if ((f = (FILE *)popen(FUNC_SPEC, "r")) == NULL) {
  205. #else
  206.     if ((f = (FILE *)fopen(FUNC_SPEC, "r")) == NULL) {
  207. #endif
  208.     perror(FUNC_SPEC);
  209.     exit(1);
  210.     }
  211.     yyparse();
  212.     /* Now sort the main_list */
  213.     for (i = 0; i < num_buff; i++) {
  214.        int j;
  215.        for (j = 0; j < i; j++)
  216.        if (strcmp(key[i], key[j]) < 0) {
  217.           char *tmp;
  218.           int tmpi;
  219.           tmp = key[i]; key[i] = key[j]; key[j] = tmp;
  220.           tmp = buf[i]; buf[i] = buf[j]; buf[j] = tmp;
  221.           tmpi = has_token[i];
  222.           has_token[i] = has_token[j]; has_token[j] = tmpi;
  223.            }
  224.     }
  225.     /* Now display it... */
  226.     printf("{\n");
  227.     for (i = 0; i < num_buff; i++)
  228.        printf("%s", buf[i]);
  229.     printf("\n};\nint efun_arg_types[] = {\n");
  230.     for (i=0; i < last_current_type; i++) {
  231.     if (arg_types[i] == 0)
  232.         printf("0,\n");
  233.     else
  234.         printf("%s,", ctype(arg_types[i]));
  235.     }
  236.     printf("};\n");
  237. #ifndef mac
  238.     pclose(f);
  239. #else
  240.     fclose(f);
  241. #endif
  242.     /*
  243.      * Write all the tokens out.  Do this by copying the
  244.      * pre-include portion of lang.y to lang.y, appending
  245.      * this information, then appending the post-include
  246.      * portion of lang.y.  It's done this way because I don't
  247.      * know how to get YACC to #include %token files.  *grin*
  248.      */
  249.     if ((fdr = open(PRE_LANG, O_RDONLY)) < 0) {
  250.        perror(PRE_LANG);
  251.        exit(1);
  252.     }
  253.     unlink(THE_LANG);
  254. #ifndef mac
  255.     if ((fdw = open(THE_LANG, O_CREAT | O_WRONLY, 0444)) < 0) {
  256. #else
  257.     if ((fdw = open(THE_LANG, O_CREAT | O_WRONLY)) < 0) {
  258. #endif
  259.        perror(THE_LANG);
  260.        exit(1);
  261.     }
  262.     while (i = read(fdr, buffer, BUFSIZ))
  263.        write(fdw, buffer, i);
  264.     close(fdr);
  265.     for (i = 0; i < num_buff; i++) {
  266.        if (has_token[i]) {
  267.           char *str;   /* It's okay to mung key[*] now */
  268.           for (str = key[i]; *str; str++)
  269.             if (islower(*str)) *str = toupper(*str);
  270.           sprintf(buffer, "%%token F_%s\n", key[i]);
  271.           write(fdw, buffer, strlen(buffer));
  272.        }
  273.     }
  274.     if ((fdr = open(POST_LANG, O_RDONLY)) < 0) {
  275.        perror(POST_LANG);
  276.        exit(1);
  277.     }
  278.     while (i = read(fdr, buffer, BUFSIZ))
  279.        write(fdw, buffer, i);
  280.     close(fdr), close(fdw);
  281.     return 0;
  282. }
  283.  
  284. void yyerror(str)
  285.     char *str;
  286. {
  287.     fprintf(stderr, "%s:%d: %s\n", FUNC_SPEC, current_line, str);
  288.     exit(1);
  289. }
  290.  
  291. int ident(c)
  292.     int c;
  293. {
  294.     char buff[100];
  295.     int len, i;
  296.  
  297.     for (len=0; isalnum(c) || c == '_'; c = getc(f)) {
  298.     buff[len++] = c;
  299.     if (len + 1 >= sizeof buff)
  300.         fatal("Local buffer in ident() too small!\n");
  301.     if (len == sizeof buff - 1) {
  302.         yyerror("Too long indentifier");
  303.         break;
  304.     }
  305.     }
  306.     (void)ungetc(c, f);
  307.     buff[len] = '\0';
  308.     for (i=0; i < NELEMS(types); i++) {
  309.     if (strcmp(buff, types[i].name) == 0) {
  310.         yylval.number = types[i].num;
  311.         return types[i].num;
  312.     }
  313.     }
  314.     if (strcmp(buff, "default") == 0)
  315.     return DEFAULT;
  316.     yylval.string = malloc(strlen(buff)+1);
  317.     strcpy(yylval.string, buff);
  318.     return ID;
  319. }
  320.  
  321. char *type_str(n)
  322.     int n;
  323. {
  324.     int i, type = n & 0xffff;
  325.  
  326.     for (i=0; i < NELEMS(types); i++) {
  327.     if (types[i].num == type) {
  328.         if (n & 0x10000) {
  329.         static char buff[100];
  330.         if (strlen(types[i].name) + 3 > sizeof buff)
  331.             fatal("Local buffer too small in type_str()!\n");
  332.         sprintf(buff, "%s *", types[i].name);
  333.         return buff;
  334.         }
  335.         return types[i].name;
  336.     }
  337.     }
  338.     return "What ?";
  339. }
  340.  
  341. int yylex1() {
  342.     register int c;
  343.     
  344.     for(;;) {
  345.     switch(c = getc(f)) {
  346.     case ' ':
  347.     case '\t':
  348.         continue;
  349.     case '#':
  350.     {
  351. #ifdef sun /* no prototype in <stdio.h> *sigh* */
  352.         extern int fscanf PROT((FILE *, char *, ...));
  353. #endif
  354.         int line;
  355.         char file[2048]; /* does any operating system support
  356.                 longer pathnames? */
  357.         if ( fscanf(f,"%d \"%s\"",&line,file ) == 2 )
  358.         current_line = line;
  359.         while(c != '\n' && c != EOF)
  360.         c = getc(f);
  361.         current_line++;
  362.         continue;
  363.     }
  364.     case '\n':
  365.         current_line++;
  366.         continue;
  367.     case EOF:
  368.         return -1;
  369.     default:
  370.         if (isalpha(c))
  371.         return ident(c);
  372.         return c;
  373.     }
  374.     }
  375. }
  376.  
  377. int yylex() {
  378.     return yylex1();
  379. }
  380.  
  381. char *etype1(n)
  382.     int n;
  383. {
  384.     if (n & 0x10000)
  385.     return "T_POINTER";
  386.     switch(n) {
  387.     case INT:
  388.     return "T_NUMBER";
  389.     case OBJECT:
  390.     return "T_OBJECT";
  391.     case STRING:
  392.     return "T_STRING";
  393.     case MAPPING:
  394.     return "T_MAPPING";
  395.     case MIXED:
  396.     return "0";    /* 0 means any type */
  397.     default:
  398.     yyerror("Illegal type for argument");
  399.     }
  400.     return "What ?";
  401. }
  402.  
  403. char *etype(n)
  404.     int n;
  405. {
  406.     int i;
  407.     int local_size = 100;
  408.     char *buff = malloc(local_size);
  409.  
  410.     for (i=0; i < curr_arg_type_size; i++) {
  411.     if (n == 0)
  412.         break;
  413.     if (curr_arg_types[i] == 0)
  414.         n--;
  415.     }
  416.     if (i == curr_arg_type_size || curr_arg_types[i] == 0)
  417.     return "0";
  418.     buff[0] = '\0';
  419.     for(; curr_arg_types[i] != 0; i++) {
  420.     char *p;
  421.     if (curr_arg_types[i] == VOID)
  422.         continue;
  423.     if (buff[0] != '\0')
  424.         strcat(buff, "|");
  425.     p = etype1(curr_arg_types[i]);
  426.     /*
  427.      * The number 2 below is to include the zero-byte and the next
  428.      * '|' (which may not come).
  429.      */
  430.     if (strlen(p) + strlen(buff) + 2 > local_size) {
  431.         fprintf(stderr, "Buffer overflow!\n");
  432.         exit(1);
  433.     }
  434.     strcat(buff, etype1(curr_arg_types[i]));
  435.     }
  436.     return buff;
  437. }
  438.  
  439. char *ctype(n)
  440.     int n;
  441. {
  442.     static char buff[100];    /* 100 is such a comfortable size :-) */
  443.     char *p;
  444.  
  445.     if (n & 0x10000)
  446.     strcpy(buff, "TYPE_MOD_POINTER|");
  447.     else
  448.     buff[0] = '\0';
  449.     n &= ~0x10000;
  450.     switch(n) {
  451.     case VOID: p = "TYPE_VOID"; break;
  452.     case STRING: p = "TYPE_STRING"; break;
  453.     case INT: p = "TYPE_NUMBER"; break;
  454.     case OBJECT: p = "TYPE_OBJECT"; break;
  455.     case MIXED: p = "TYPE_ANY"; break;
  456.     case MAPPING: p = "TYPE_MAPPING"; break;
  457.     case UNKNOWN: p = "TYPE_UNKNOWN"; break;
  458.     default: yyerror("Bad type!");
  459.     }
  460.     strcat(buff, p);
  461.     if (strlen(buff) + 1 > sizeof buff)
  462.     fatal("Local buffer overwritten in ctype()");
  463.     return buff;
  464. }
  465.